package com.divillysausages.dsair.settings 
{
	import com.divillysausages.dsair.DSAir;
	import flash.net.registerClassAlias;
	import flash.net.SharedObject;
	import flash.utils.ByteArray;
	import flash.utils.getQualifiedClassName;
	
	/**
	 * The manager that deals with saving different settings for our app
	 * 
	 * NOTE: a big 100% FUCK YOU to whichever dickhead made this implementation. For some
	 * fucking reason, the deserialisation of the fucking lso will only work in certain
	 * cases; namely I can't hold it as a class prop, and I can't use certain name. Like
	 * "_dsAppSettings" will work, but not "dsAppSettings". Go fucking figure that one out.
	 * @author Damian Connolly
	 */
	public class SettingsManager 
	{
		
		/********************************************************************/
		
		private static var m_instance:SettingsManager	= null;	// the only instance of the settings manager
		private static var m_creating:Boolean			= false;// are we creating the settings manager?
		
		/********************************************************************/
		
		/**
		 * The singleton instance for the resource manager
		 */
		public static function get instance():SettingsManager
		{
			if ( SettingsManager.m_instance == null )
			{
				SettingsManager.m_creating = true;
				SettingsManager.m_instance = new SettingsManager;
				SettingsManager.m_creating = false;
			}
			return SettingsManager.m_instance;
		}
		
		/********************************************************************/
		
		private const M_LSO_NAME:String			= "_dsAppSettings"; // the name for the local shared object
		private const M_SETTINGS_NAME:String 	= "settings"; 		// the name for our object in our lso
		
		/********************************************************************/
		
		/**
		 * Creates a SettingsManager. As SettingsManager is a singleton, this shouldn't be called
		 * directly, but rather the static instance getter instead
		 */
		public function SettingsManager() 
		{
			if ( !SettingsManager.m_creating )
				throw new Error( "SettingsManager is a singleton. Use the static instance getter instead" );
		}
		
		/**
		 * Gets the settings that we've saved in our local shared object
		 * @return The settings, or null if we haven't saved any
		 */
		public function get():*
		{
			// get our shared object
			var lso:SharedObject = null;
			try { lso = SharedObject.getLocal( this.M_LSO_NAME ); }
			catch ( e:Error ) { }
			
			// no object, no data
			if ( lso == null )
				return null;
				
			// no data, return
			if ( !( this.M_SETTINGS_NAME in lso.data ) )
				return null;
				
			// get our bytes
			var bytes:ByteArray = lso.data[this.M_SETTINGS_NAME] as ByteArray;
			if ( bytes == null )
				return;
				
			// uncompress our bytearray
			try { bytes.uncompress(); }
			catch ( e:Error ) { }
			
			// read and return the object
			bytes.position = 0;
			return bytes.readObject();
				
			// return the data
			return lso.data[this.M_SETTINGS_NAME];
		}
		
		/**
		 * Clear the settings
		 */
		public function clear():void
		{
			var lso:SharedObject = null;
			
			// try and get the shared object
			try	{ lso = SharedObject.getLocal( this.M_LSO_NAME );}
			catch ( e:Error ) { }
			
			// clear it
			lso.clear();
		}
		
		/**
		 * Saves the settings
		 * @param data The data to save
		 * @return If the data was successfully saved or not
		 */
		public function save( data:* ):Boolean
		{
			// get our shared object
			var lso:SharedObject = null;
			try { lso = SharedObject.getLocal( this.M_LSO_NAME ); }
			catch ( e:Error ) { }
			
			// no object, no data
			if ( lso == null )
			{
				DSAir.warn( this, "Can't save the settings data" );
				return false;
			}
			
			// create our byte array
			var bytes:ByteArray = new ByteArray;
			bytes.writeObject( data );
			bytes.compress();
			
			// set our data
			lso.data[this.M_SETTINGS_NAME] = bytes;
			
			// try and save it
			try	{ lso.flush(); }
			catch ( e:Error )
			{
				DSAir.error( this, "Couldn't save the settings" );
				return false;
			}
			
			// it worked
			return true;
		}
		
		/**
		 * Registers a class so that when we retrieve the settings it deserialises properly
		 * @param clazz The class to save
		 */
		public function registerClass( clazz:Class ):void
		{
			registerClassAlias( getQualifiedClassName( clazz ), clazz );
		}
		
	}

}